package com.brycen.nio.chat;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Scanner;

/**
 * 结合buffer、channel、selector做的综合应用
 */
public class Client {

    private SocketChannel socketChannel;

    private Selector selector;
    private int PORT=9999;

    public Client(){
        try {
            //创建客户端通道
            socketChannel = SocketChannel.open(new InetSocketAddress("127.0.0.1", PORT));
            //设置非阻塞
            socketChannel.configureBlocking(false);
            //创建选择器
            selector = Selector.open();
            //将客户端通道注册到选择器上，注册模式为读
            socketChannel.register(selector, SelectionKey.OP_READ);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        Client client = new Client();

        new Thread(new Runnable() {
            @Override
            public void run() {
                //开启一个线程读取服务端发送过来的信息
                client.readInfo();
            }
        }).start();

        Scanner scanner = new Scanner(System.in);
        System.out.print("请输入用户名：");
        String name = scanner.nextLine();
        while (true){
            String s = name+"说："+scanner.nextLine();
            //发送数据到服务器
            client.sendToServer(s);
        }
    }

    private void sendToServer(String data) {
        try {
            socketChannel.write(ByteBuffer.wrap(data.getBytes()));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void readInfo() {
        try {
            //判断选择器中是否有准备好的事件，如果没有则进行阻塞
            while (selector.select()>0){
                Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
                while (iterator.hasNext()){
                    SelectionKey sk = iterator.next();
                    //判断该事件是否是读事件
                    if (sk.isReadable()){
                        //获取事件对应的通道
                        SocketChannel channel = (SocketChannel) sk.channel();
                        ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
                        int len;
                        //读取数据
                        while ((len = channel.read(byteBuffer))>0){
                            System.out.println(new String(byteBuffer.array(),0,byteBuffer.remaining()));
                        }
                        //如果数据长度是-1则表示断开连接
                        if (len==-1){
                            closeClient();
                        }
                    }
                }
                //事件处理完成，移除该事件
                iterator.remove();
            }
        }catch (Exception e){
            closeClient();
            e.printStackTrace();
        }

    }

    private void closeClient() {
        try {
            selector.close();
            socketChannel.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
